package cn.cellcom.agent.online.iq.visitor;

import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.cellcom.agent.biz.TGroupBiz;
import cn.cellcom.agent.common.AgentConstant;
import cn.cellcom.agent.common.AgentConstant.ENTER_GROUP_RESULT;
import cn.cellcom.agent.online.client.Client;
import cn.cellcom.agent.online.client.QueueManager;
import cn.cellcom.agent.online.client.VisitorClient;
import cn.cellcom.agent.online.iq.AbstractChainedProcessor;
import cn.cellcom.agent.online.iq.Processor;
import cn.cellcom.agent.online.iq.ProcessorResult;
import cn.cellcom.agent.online.message.MessageConstant;
import cn.cellcom.agent.online.message.MessageConstant.ARCHIVE_EVENT;
import cn.cellcom.agent.online.message.MessageConstant.ARCHIVE_SHOW_POLICY;
import cn.cellcom.agent.online.message.MessageConstant.MESSAGE_NOTIFY;
import cn.cellcom.agent.online.message.MessageReceipt;
import cn.cellcom.agent.online.wrapper.GroupWrapper;
import cn.cellcom.agent.online.wrapper.SessionWrapper;
import cn.cellcom.agent.pojo.TGroup;
import cn.cellcom.agent.pojo.TSession;
import cn.cellcom.agent.struts.form.VisitorForm;
import cn.cellcom.jar.biz.AbstractBiz;
import cn.cellcom.jar.util.MyException;

public class EnterGroupProcessor extends AbstractChainedProcessor {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	public EnterGroupProcessor(Processor next) {
		super(next);
	}

	/**
	 * 进入技能组,两种情况: <br>
	 * 1 选择之后进入自助聊天 <br>
	 * 2 自助聊天之后要求转人工 <br>
	 * 3 选择技能组之后直接转人工 只有配置了进技能组之后自助服务以及当前处于无技能组状态才进入自助服务,其他情况就是要转人工了
	 * 
	 * @param group
	 * @param user
	 */
	@Override
	public ProcessorResult doProcess(Map<String, AbstractBiz> bizs, Client client, VisitorForm cf) {
		VisitorClient ac = (VisitorClient) client;
		SessionWrapper session = ac.getSessionByPid(cf.getPid());
		if (session == null) {
			log.error("[{}] no session exist for archive for pid[{}]", ac.getId(), cf.getPid());
			return new ProcessorResult(false, this, null);
		}
		String sid = session.getId();
		String groupId = cf.getValue();
		log.info("[{}] enter group[{}] in session[{}]", ac.getId(), groupId, sid);
		if (StringUtils.isBlank(groupId) && session.getGroup() == null) {// 20180602:新增微信渠道之后，66进入人工时没有再次带入技能组，所以增加判断：
																			// && session.getGroup() == null
			log.error("[{}] no groupid exist for archive for pid[{}]", ac.getId(), cf.getPid());
			return new ProcessorResult(false, this, null);
		} else if (session.getGroup() == null) {
			TGroupBiz gbiz = (TGroupBiz) bizs.get("gbiz");
			try {
				GroupWrapper v = gbiz.loadGroupToMemory(groupId);
				session.setGroup(v);
			} catch (MyException e) {
				log.error("[{}] load group[{}] fail.", ac.getId(), groupId);
				return new ProcessorResult(false, this, null);
			}
		}
		TGroup g = null;
		if (session.getGroup() != null) {
			g = session.getGroup().getGroup();
		}
		ac.archiveWithId(session, cf.getId(), cf.getEvent(), cf.getValue(), cf.getMultiType(), g == null ? "" : g.getName());
		/**
		 * 1、修改session内存<br>
		 * 2、存储<br>
		 * 3、通知会话<br>
		 * 4、通知状态<br>
		 * 5、其他
		 */
		ENTER_GROUP_RESULT result = null;
		TSession s = session.getSession();
		// 配置了选择组之后进行自助聊天，并且首次选择技能组（request group is
		// null）【这种机制下已经在前端实现了：访问时知获取企业的开关，调用接口读取技能组列表，然后直接显示技能组了】
		if (session.getSetting().getSelfPolicy() == AgentConstant.SELF_POLICY.AFTER_GROUP.ordinal() && StringUtils.isBlank(s.getRequestGroup())) {
			log.info("[{}] enter group and transfer to self talking in session[{}]", ac.getId(), session.getId());

			s.setStep(AgentConstant.SESSION_STEP.SELF.name());
			s.setRobotTime(System.currentTimeMillis());
			s.setRequestGroup(groupId);// 记录会话请求的技能组
			ac.updateSessionDb(s);
			ac.sendSession(session.getSession());
			ac.notifyStatus(session.getPid(), null);
			result = ENTER_GROUP_RESULT.SELF;
		} else {
			// 如果不是服务时间，则可能不提供服务
			if (session.getSetting().offdutyTime()) {
				if (AgentConstant.on.equals(session.getSetting().getOffdutyReject())) {// 下班时间不提供服务
					session.getSystem().sysSendText(session.getSetting().getOffdutyRejectTip());
					return new ProcessorResult(true, this, null);
				} else {// 下班时间虽然接入，但是可能要提示繁忙
					session.getSystem().sysSendText(session.getSetting().getOffdutyReceiptTip());
				}
			}

			// 无坐席时不可排队
			if (session.getGroup().countAgents() == 0
					&& session.getSetting().getNoOnlineAgentPolicy() == AgentConstant.NO_ONLINE_AGENT_POLICY.DISABLE.ordinal()) {
				log.info("[{}] enter group and but no agent exist so rejected in session[{}]", ac.getId(), session.getId());
				if(StringUtils.isBlank(s.getRequestGroup())) {
					s.setRequestGroup(groupId);// 记录会话请求的技能组
				}
				ac.updateSessionDb(s);
				// 如果本身处于机器人聊天,则提示可以继续机器人聊天
				MESSAGE_NOTIFY ntfy = s.getStep().equals(AgentConstant.SESSION_STEP.SELF.name()) ? MESSAGE_NOTIFY.CONTINUE_SELF
						: MESSAGE_NOTIFY.NO_AGENT_ONLINE ;
				session.getSystem().sysSendNotify(ac.getId(), ntfy, null);
				session.getSystem().sysSendText(session.getSetting().getNoAgentOnlineTip());
				ac.sendSession(session.getSession());

				result = ENTER_GROUP_RESULT.NO_AGENT_ONLINE;
			} else {// 有坐席在线则可以进入排队，或者配置策略为无坐席也可以排队
				log.info("[{}] enter group and transfer to queue in session[{}]", ac.getId(), session.getId());

				long qt = System.currentTimeMillis();
				int position = QueueManager.getInstance().getQueue(session.getPid()).addQueue(session);
				if (position == -1) {
					s.setQueueTime(qt);
					s.setStep(AgentConstant.SESSION_STEP.AGENT.name());
					if(StringUtils.isBlank(s.getRequestGroup())) {
						s.setRequestGroup(groupId);// 记录会话请求的技能组
					}
					ac.updateSessionDb(s);
					ac.sendSession(session.getSession());
					result = ENTER_GROUP_RESULT.AGENT;
				} else {
					// 进入对应的技能组
					s.setQueueTime(System.currentTimeMillis());
					s.setStep(AgentConstant.SESSION_STEP.QUEUE.name());
					if(StringUtils.isBlank(s.getRequestGroup())) {
						s.setRequestGroup(groupId);// 记录会话请求的技能组
					}
					ac.updateSessionDb(s);
					ac.sendSession(session.getSession());
					ac.notifyStatus(session.getPid(), null);
					result = ENTER_GROUP_RESULT.QUEUE;
				}
			}
		}
		// 消息归档
		ac.archive(session, ARCHIVE_EVENT.ENTER_GROUP_RESULT, result.name(), ARCHIVE_SHOW_POLICY.MANAGER_AND_AGENT);
		if (result.equals(ENTER_GROUP_RESULT.ERROR)) {
			return new ProcessorResult(false, this, new MessageReceipt(cf.getId(), true));
		}
		return new ProcessorResult(true, this, new MessageReceipt(cf.getId(), true));
	}

	@Override
	public boolean isAcceptable(VisitorForm cf) {
		return MessageConstant.MESSAGE_EVENT.ENTER_GROUP.name().equals(cf.getEvent());
	}
}
